package model;

import interfaces.AbstractDrink;
import interfaces.AbstractFood;
import interfaces.AbstractWish;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import enums.State;

public class Model {
	public boolean inAppFocus = false;
	private int notificationCount = 0;
	// Lebensmitteln
	public static final String LEBENSMITTEL_KARTOFFELN = "Kartoffeln";
	public static final String LEBENSMITTEL_GURKE = "Gurke";
	public static final String LEBENSMITTEL_TOMATE = "Tomate";
	public static final String LEBENSMITTEL_ERBSEN = "Erbsen";
	public static final String LEBENSMITTEL_FLEISCH = "Fleisch";
	public static final String LEBENSMITTEL_BOCKWURST = "Bockwurst";
	public static final String LEBENSMITTEL_BROT = "Brot";
	public static final String LEBENSMITTEL_BROETCHEN = "Brötchen";
	public static final String LEBENSMITTEL_GRIESS = "Griess";
	public static final String LEBENSMITTEL_HAFERFLOCKEN = "Haferflocken";
	public static final String LEBENSMITTEL_MILCH = "Milch";
	public static final String LEBENSMITTEL_WASSER = "Wasser";
	public static final String LEBENSMITTEL_TEE = "Tee";
	public static final ArrayList<String> ingredientsNames() {
		ArrayList<String> list = new ArrayList<String>();
		list.add(LEBENSMITTEL_KARTOFFELN);
		list.add(LEBENSMITTEL_GURKE);
		list.add(LEBENSMITTEL_TOMATE);
		list.add(LEBENSMITTEL_ERBSEN);
		list.add(LEBENSMITTEL_FLEISCH);
		list.add(LEBENSMITTEL_BOCKWURST);
		list.add(LEBENSMITTEL_BROT);
		list.add(LEBENSMITTEL_BROETCHEN);
		list.add(LEBENSMITTEL_GRIESS);
		list.add(LEBENSMITTEL_HAFERFLOCKEN);
		list.add(LEBENSMITTEL_MILCH);
		list.add(LEBENSMITTEL_WASSER);	
		return list;
	}
	// Speisen
	public static final String SPEISE_SCHNITZEL = "Schnitzel";
	public static final String SPEISE_CHEESBURGER = "Cheesburger";
	public static final String SPEISE_STEAK = "Steak";
	public static final String SPEISE_BOCKWURST_MIT_KARTOFFELN = "Bockwurst mit Kartoffeln";
	public static final String SPEISE_ERBSENEINTOPF = "Erbseneintopf";
	public static final String SPEISE_GRIESSBREI = "Grießbrei";
	public static final String SPEISE_SANDWICH = "Sandwich";
	public static final String SPEISE_SALAT = "Salat";
	public static final String SPEISE_HAFERFLOCKEN_MIT_MILCH = "Haferflocken mit Milch";
	public static final ArrayList<String> foodNames() {
		ArrayList<String> list = new ArrayList<String>();
		list.add(SPEISE_SCHNITZEL);
		list.add(SPEISE_CHEESBURGER);
		list.add(SPEISE_STEAK);
		list.add(SPEISE_BOCKWURST_MIT_KARTOFFELN);
		list.add(SPEISE_ERBSENEINTOPF);
		list.add(SPEISE_GRIESSBREI);
		list.add(SPEISE_SANDWICH);
		list.add(SPEISE_SALAT);
		list.add(SPEISE_HAFERFLOCKEN_MIT_MILCH);	
		return list;
	}
	// Zeit
	public static final long ZEIT_SEKUNDE = 1000;
	public static final long ZEIT_MINUTE = ZEIT_SEKUNDE * 60;
	public static final long ZEIT_STUNDE = ZEIT_MINUTE * 60;
	public static final long ZEIT_TAG = ZEIT_STUNDE * 24;
	public static final long ZEIT_WOCHE = ZEIT_TAG * 7;
	// Kleidung
	public static final int KLEIDUNG_MAX_ANZAHL = 6; 
	public static final String KLEIDUNG_NACHTHEMD = "Nachthemd";
	public static final String KLEIDUNG_KLEID = "Kleid";
	public static final ArrayList<String> clothesNames() {
		ArrayList<String> list = new ArrayList<String>();
		list.add(KLEIDUNG_KLEID);
		list.add(KLEIDUNG_NACHTHEMD);	
		return list;
	}
	// Lager
	public static final int LAGER_MAX_ANZAHL = 10;
	// Medizin
	public static final String MEDIZIN_MORGENS = "Morgens";
	public static final String MEDIZIN_MITTAGS = "Mittags";
	public static final String MEDIZIN_ABENDS = "Abends";
	// Schlafen
	public static final long SCHLAFEN_KURZ = ZEIT_SEKUNDE * 10;
	public static final long SCHLAFEN_LANG = ZEIT_STUNDE * 9;
	// Geschir
	public static final int GESCHIRR_MAX_ANZAHL = 5;
	public static final String GESCHIRR_GABEL = "Gabel";
	public static final String GESCHIRR_MESSER = "Messer";
	public static final String GESCHIRR_LOEFFEL = "Löffel";
	public static final String GESCHIRR_TELLER = "Teller";
	public static final String GESCHIRR_BECHER = "Becher";
	public static final String GESCHIRR_GLAS = "Glas"; 
	public static final ArrayList<String> dishesNames() {
		ArrayList<String> list = new ArrayList<String>();
		list.add(GESCHIRR_BECHER);
		list.add(GESCHIRR_GABEL);
		list.add(GESCHIRR_GLAS);
		list.add(GESCHIRR_LOEFFEL);
		list.add(GESCHIRR_MESSER);
		list.add(GESCHIRR_TELLER);
		return list;
	}

	// M E M B E R
	private Wishes wishes;
	private Stock stock;
	private Wardrobe wardrobe;
	private Cupboard cupboard;
	private ShoppingList shoppingList;
	private static Model instance;
	private long startTimeToSleep;
	private long wakeUpTime;
	private State state;

	public static Model getInstance() {
		if (instance == null) {
			instance = new Model();
		}		
		return instance;
	}

	public static void destroyInstance() {
		if (instance != null) {
			instance = null;
		}
	}
	private Model() {
		init();	
	}
	private void init() {
		wishes = new Wishes();
		stock = new Stock(LAGER_MAX_ANZAHL, LAGER_MAX_ANZAHL, ingredientsNames());
		wardrobe = new Wardrobe(KLEIDUNG_MAX_ANZAHL, KLEIDUNG_MAX_ANZAHL, clothesNames());
		cupboard = new Cupboard(GESCHIRR_MAX_ANZAHL, GESCHIRR_MAX_ANZAHL, dishesNames());
		shoppingList = new ShoppingList(0, LAGER_MAX_ANZAHL, ingredientsNames());
		wakeUp();
	}

	// Wandelt Millisekunden in eine Uhrzeit als Text um
	public static String millisToString(long millis) {
		Date date = new Date(millis);
		DateFormat df = new SimpleDateFormat("HH:mm:ss");
		return df.format(date);
	}
	// Erstellt eine Zufallszahl in dem Bereich von min bis max
	public static final int random(int min, int max) {
		int MIN = Math.min(min, max);
		int MAX = Math.max(min, max);
		int random = (int)(Math.random()*(MAX - MIN + 1)) + MIN;
		return random;
	}

	// Ist die Oma noch am Leben?
	public boolean grandmaIsAlive() {
		for (AbstractWish wish : wishes) {
			if (wish.hasExpired()) {
				return false;
			}
		}
		return true;
	}

	// Es ist wieder mal Zeit zu putzen
	public static boolean isTimeToCleanApartment(long now) {
		// Jeden Montag um 12:00 soll geputzt werden
		Date date = new Date(now);
		if (date.getDay() == Calendar.SATURDAY && date.getHours() >= 1  && date.getHours() < 13) {
			return true;
		}
		return false;
	}

	// ist es Zeit zu schlafen?
	public static boolean isTimeToSleep(long now) {
		int min = 20;	// Oma wird müde und will ins Bett
		int max = 21;
		Date date = new Date(now);
		if (date.getHours() >= min && date.getHours() < max) {
			return true;
		}
		return false;
	}

	// ist es Zeit aufzuwachen?
	public boolean isTimeToWakeUp(long now) {
		//	if ((millis >= wakeUpTime) && isSleeping) {
		if (now >= wakeUpTime && state == State.Sleeping) {
			return true;
		}
		return false;
	}
	// Ist es Zeit zum Frühstücken
	public static boolean isTimeForBreakfast(long now) { 
		int von = 8;	// Frühstück zwischen 8 und 9 Uhr
		int bis = 9;
		Date date = new Date(now);
		if (date.getHours() >= von && date.getHours() < bis) {
			return true;
		}
		return false;
	}
	// Ist es Zeit für Mittagsessen
	public static boolean isTimeForLunch(long now) {
		int von = 13;
		int bis = 14;
		Date date = new Date(now);
		if (date.getHours() >= von && date.getHours() < bis) {
			return true;
		}
		return false;
	}
	// Ist es Zeit  für Abendessen?
	public static boolean isTimeForDinner(long now) {
		int von = 16;	// Abendessen
		int bis = 17;
		Date date = new Date(now);
		if (date.getHours() >= von && date.getHours() < bis) {
			return true;
		}
		return false;
	}

	// Einkaufen
	public void buy(String key, int value) {
		stock.add(key, value);
		shoppingList.remove(key, value);
	}

	// Oma einkleiden, mit Nachthemd oder Kleid
	public void fitOut(String name) {
		if (wardrobe.contains(name, 1)) {
			wardrobe.remove(name, 1);
		}
	}
	// Kleidung waschen
	public void washClothes() {
		wardrobe.init();
		fitOut(KLEIDUNG_KLEID);
	}
	// Geschirr abwaschen
	public void washDishes() {
		cupboard.init();
	}
	// Geschirr verbrauchen
	public void useDishes(HashMap<String, Integer> map) {
		if (cupboard.contains(map)) {
			cupboard.remove(map);
		}
	}

	public void cleanApartment() {}

	// Trinken
	public void drink(AbstractDrink drink) {
		// Aus dem Lager werden Lebensmitteln entnommen, in diesem Fall Wasser
		stock.remove(drink.getIngredients());
		useDishes(drink.getDishes());
	}
	// Essen
	public void eat(AbstractFood food) {
		long now = System.currentTimeMillis();
		// aus dem Lager werden Lebensmitteln entfernt
		stock.remove(food.getIngredients());
		useDishes(food.getDishes());
		// Schweres Essen zu Mittag benötigt Medizin
		if (isTimeForLunch(now) && food.isHeavy()) {
			// Erstelle einen Wunsch nach Medizin
			AbstractWish wish = WishFactory.createWishToTakeMedicine(MEDIZIN_MITTAGS);
			if (wish != null) {
				System.out.println(wish.toString());
			}
		}
	}
	// Schlafen
	public void sleep(long timeToSleep) {
		state = State.Sleeping;
		fitOut(KLEIDUNG_NACHTHEMD);
		wakeUpTime = (System.currentTimeMillis() + timeToSleep);
	}
	// Aufwachen
	public void wakeUp() {
		state = State.Awake;
		fitOut(KLEIDUNG_KLEID);
		wakeUpTime = 0;
	}

	public int addNotificationCount() {
		notificationCount++;
		return notificationCount;
	}

	// GETTER AND SETTER
	public Wardrobe getCLothes() {
		return wardrobe;
	}
	public Wishes getWishes() {
		return wishes;
	}
	public Stock getStock() {
		return stock;
	}
	public ShoppingList getShoppingLIst() {
		return shoppingList;
	}
	public Cupboard getDishes() {
		return cupboard;
	}

	public long getSleepStartTime() {
		return startTimeToSleep;
	}
	public void setStartTimeToSleep(long time) {
		this.startTimeToSleep = time;
	}

	public State getState() {
		return state;
	}
	public void setState(State state) {
		this.state = state;
	}

	public long getWakeUpTime() {
		return wakeUpTime;
	}
	public void setWakeUpTime(long wakeUpTime) {
		this.wakeUpTime = wakeUpTime;
	}
	public int getNotificationCount() {
		return notificationCount;
	}
	public void setNotificationCount(int notificationCount) {
		this.notificationCount = notificationCount;
	}
}